package cn.dragon.eatingfish;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public abstract class SeaObject {
    public static final int LIVE = 0; // 活着的
    public static final int DEAD = 1; // 死了的
    public final static int M_LEFT = -1; // 鱼头朝左
    public final static int M_RIGHT = 1; // 鱼头朝右
    private int state = LIVE; // 当前状态(默认活着)
    private int direction = M_LEFT; // 鱼头方向默认向左

    private boolean flag = false; // 攻击范围内控制只能转向一次的标志

    private int width;
    private int height;
    private int life;
    private int level; // public
    private int x;
    private int y;
    private int speed;
    private int truns;   // 允许鱼的转向次数
    private boolean freezing = false;


    public SeaObject() {

    }

    // NPC的构造方法
    public SeaObject(int width, int height, int life, int level, int speed) {
        this.width = width;
        this.height = height;
        this.life = life;
        this.level = level;
        this.speed = speed;
        this.x = getInitial_NPC_X(); // 获取NPC初始x坐标
        this.y = new Random().nextInt(700);
        this.truns = new Random().nextInt(5); // 随机生成鱼的转向次数

        if (this.x == 1400) { // 起始位置从右边出来
            this.direction = M_LEFT; // 鱼头向左
        } else {
            this.direction = M_RIGHT;
        }
    }

    // x坐标实现最左边或最右边生成
    public int getInitial_NPC_X() {
        Random random = new Random();
        int a = random.nextInt(100);
        if (a >= 50) { // 一半几率从左边出来
            return -width;
        } else { // 一半几率从右边出来
            return World.WIDTH;
        }
    }


    // NPC的移动
    public void move(SeaObject majorFish) {
        if (this.level > majorFish.getLevel()) { // npc等级大于主角鱼
            if (inRange(majorFish, this)) { // 在npc范围内
                // 靠近主角鱼
                if (this.y >= majorFish.y) { // npc在主角鱼下方
                    y = y - speed / 2;
                } else { // npc在主角鱼上方
                    y = y + speed / 2;
                }

                // npc刚过主角鱼右边且鱼头朝右、转向次数还有
                if (this.x > majorFish.x && this.direction == M_RIGHT && !flag && this.truns > 0 && this.freezing == false) {
                    this.direction = M_LEFT; // 调转鱼头
                    this.truns--; // 调转次数-1
                    flag = true; // 在范围内只能转一次
                }


                // npc刚过主角鱼左边且鱼头朝左、转向次数还有
                if (this.x < majorFish.x && this.direction == M_LEFT && !flag && this.truns > 0 && this.freezing == false) {
                    this.direction = M_RIGHT;
                    this.truns--;
                    flag = true;
                }

            } else { // 出范围外不限制转向次数
                flag = false;
            }

            if (this.direction == M_LEFT) { // npc鱼头向左走
                x -= speed;
            } else { // npc鱼头向右走
                x += speed;
            }

        } else {  // npc等级小于主角鱼
            if (this.direction == M_LEFT) {
                x -= speed;
            } else {
                x += speed;
            }

            if (inRange(majorFish, this)) { // 在npc范围内
                // 远离主角鱼
                if (this.y >= majorFish.y) { // npc在主角鱼下方
                    y = y + speed;
                } else {
                    y = y - speed;
                }

            }
        }
    }


    public boolean isLive() {
        return state == LIVE;
    }

    public boolean isDead() {
        return state == DEAD;
    }

    public abstract ImageIcon getImage();

    public void goDead() {
        state = DEAD;
    }

    public boolean isOutOfBounds() {
        return (this.x >= World.WIDTH) || (this.x <= -width);
    }


    // 判断是否在攻击范围内
    public boolean inRange(SeaObject majorFish, SeaObject npc) {
        // 两点间的距离的小于主角鱼等级*8+220
        return Math.sqrt(Math.pow((majorFish.x + majorFish.width / 2) - (npc.x + npc.width / 2), 2)
                + Math.pow((majorFish.y + majorFish.height / 2) - (npc.y + npc.height / 2), 2))
                <= majorFish.getLevel() * 8 + 220;
    }

    // 两者是否碰到
    public boolean isHit(SeaObject other) { // other是主角鱼
        // 考虑到白板比鱼本身长、宽，将碰撞范围缩小一点
        int x1 = this.x - other.width;  // npc.x - major.width - level * 10
        int y1 = this.y - other.height; // npc.y - major.width - level * 10
        int x2 = this.x + this.width;// npc.x + npc.width - level * 10
        int y2 = this.y + this.height;  // npc.y + npc.height - level * 10
        int x = other.x; // 主角鱼的x
        int y = other.y; // 主角鱼的y

        return x >= x1 && x <= x2
                &&
                y >= y1 && y <= y2; // x在x1与x2之间，并且，y在y1与y2之间，即为撞上了
    }


    // 吃鱼之前比较主角鱼与等级
    public boolean compareLevel(SeaObject majorfish) {
        // 主角鱼等级 >= npc等级
        return this.level <= majorfish.level;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public int getDirection() {
        return direction;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getLife() {
        return life;
    }

    public void setLife(int life) {
        this.life = life;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getTruns() {
        return truns;
    }

    public void setTruns(int truns) {
        this.truns = truns;
    }

    public void paintImage(Graphics g) {
        this.getImage().paintIcon(null, g, this.x, this.y);
    }

    public boolean isFreezing() {
        return freezing;
    }

    public void setFreezing(boolean freezing) {
        this.freezing = freezing;
    }

    public abstract int getScore();

}
